1 Read and Merge

The working directory was changed to E:/Cinetic idei noi/EXPERIMENTE OGL Frontiers (O.2 & O.0.3 & O.0.2) inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.

Merge was succesful

2 Derive new variables

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Derive new variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Data$D_VasS_Poz <- Data[, "VasS_postPoz"] - Data[, "VasS_prePoz"] 
Data$D_VasS_Neg <- Data[, "VasS_postNeg"] - Data[, "VasS_preNeg"]
Data$D_VasB_Poz <- Data[, "VasB_postPoz"] - Data[, "VasB_prePoz"] 
Data$D_VasB_Neg <- Data[, "VasB_postNeg"] - Data[, "VasB_preNeg"]
Data$D_IOS_Poz <- Data[, "IOS_postPoz"] - Data[, "IOS_prePoz"] 
Data$D_IOS_Neg <- Data[, "IOS_postNeg"] - Data[, "IOS_preNeg"]

Data$D_Sam1_Poz <- Data[, "Sam1_postPoz"] - Data[, "Sam1_prePoz"] 
Data$D_Sam1_Neg <- Data[, "Sam1_postNeg"] - Data[, "Sam1_preNeg"]
Data$D_Sam2_Poz <- Data[, "Sam2_postPoz"] - Data[, "Sam2_prePoz"] 
Data$D_Sam2_Neg <- Data[, "Sam2_postNeg"] - Data[, "Sam2_preNeg"]
Data$D_Sam3_Poz <- Data[, "Sam3_postPoz"] - Data[, "Sam3_prePoz"] 
Data$D_Sam3_Neg <- Data[, "Sam3_postNeg"] - Data[, "Sam3_preNeg"]

Data$D_DG_Poz <- Data[, "DG_postPozTot"] - Data[, "DG_prePozTot"] 
Data$D_DG_Neg <- Data[, "DG_postNegTot"] - Data[, "DG_preNegTot"]

Data$D_TrustMin_Poz <- Data[, "TrustMinPozPost"] - Data[, "TrustMinPozPre"] 
Data$D_TrustMin_Neg <- Data[, "TrustMinNegPost"] - Data[, "TrustMinNegPre"]
Data$D_TrustTot_Poz <- Data[, "TrustTotPozPost"] - Data[, "TrustTotPozPre"] 
Data$D_TrustTot_Neg <- Data[, "TrustTotNegPost"] - Data[, "TrustTotNegPre"]

Data$D_Cort_Poz <- Data[, "Cort_post_Poz"] - Data[, "Cort_pre_Poz"] 
Data$D_Cort_Neg <- Data[, "Cort_post_Neg"] - Data[, "Cort_pre_Neg"]
Data$D_Ox_Poz <- Data[, "Ox_post_Poz"] - Data[, "Ox_pre_Poz"] 
Data$D_Ox_Neg <- Data[, "Ox_post_Neg"] - Data[, "Ox_pre_Neg"]

3 Define Functions

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for mining correlations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Function for p-value significance -- both for func_ancova_multibox(), Get_Top_Relationships() and Correlations_With_One()
stars_signif <- function(pval) {
  stars = "ns"
  if(pval <= 0.001)
    stars = "***"
  if(pval > 0.001 & pval <= 0.01)
    stars = "**"
  if(pval > 0.01 & pval <= 0.05)
    stars = "*"
  if(pval > 0.05 & pval <= 0.1)
    stars = "."
  stars
}

## Function that returns correlations of all variables in descending order.
# Arg for threshold with default at .3 will keep only correlantions above .3 and below -.3. Also has threshhold for p-value. 
Get_Top_Relationships <- function(data_set, 
                                  correlation_abs_threshold=0.3,
                                  pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  feature_names <- names(data_set)
  # strip var names to index for pair-wise identification
  names(data_set) <- seq(1:ncol(data_set))
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set)
  # apply var names to correlation matrix over index
  rownames(cor_data_df$r) <- feature_names
  colnames(cor_data_df$r) <- feature_names
  # top cor and sig
  relationships_set <- cor_data_df$ci[,c('r','p')]
  # apply var names to data over index pairs
  relationships_set$feature_1 <- feature_names[as.numeric(sapply(strsplit(rownames(relationships_set), "-"), `[`, 1))]
  relationships_set$feature_2 <- feature_names[as.numeric(
    sapply(strsplit(rownames(relationships_set), "-"), `[`, 2))]
  relationships_set <- dplyr::select(relationships_set, feature_1, feature_2, r, p) %>% dplyr::rename(correlation = r, p.value = p)
  # return only the most insteresting relationships
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
        arrange(p.value) %>%
        mutate(p.signif = sapply(p.value, function(x) stars_signif(x))))
}

## Function that returns all correlation between numeric variables and one specific variable
Correlations_With_One <- function(data_set,
                            variable,
                            correlation_abs_threshold=0.3,
                            pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  # use all numeric columns only
  numeric_cols <- unlist(lapply(data_set, is.numeric))
  data_set <- data_set[, numeric_cols]                               
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set[, names(data_set) != variable], data_set[, variable], minlength = 20, adjust="none")
  # top cor and sig
  relationships_set <- as.data.frame(cbind(cor_data_df$r, cor_data_df$p))     # same as  cor_data_df$ci[,c('r','p')]
  relationships_set <- tibble::rownames_to_column(relationships_set, "Variable")   # relationships_set$Variable <- rownames(relationships_set)
  colnames(relationships_set) <- c("Variable", "correlation", "p.value")
  # return only the most insteresting relationships
  cat("#### Correlations with ", variable, "\n")
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
           arrange(p.value) %>%
           mutate(p.signif = sapply(p.value, function(x) stars_signif(x)))) %>%
           tibble::as.tibble()
}  


## Function for ploting correlation data frames resulting from Get_Top_Relationships and Correlations_With_One()
func_dotplot_cor <- function(df){                                        # https://www.r-pkg.org/pkg/ggpubr
  dotplotcor_scale_fill <- function(...){                                # Fix colors to signif factor levels even if missing
    ggplot2:::manual_scale(                                   
      'color', 
      values = setNames(
        c("darkgreen", "green3", "lawngreen", "yellow", "red"), 
        c("***", "**", "*", ".", "ns")), 
      ...
    )
  }                                           
  
  dtoplot_theme <- 
    ggpubr::theme_pubr() +
    theme(axis.text.y = element_text(size = 10))
  
  if(!"Variable" %in% colnames(df)){                                             # in oder to work for both Get_Top_Relationships and Correlations_With_One()
  df <- 
    df %>%                                            
      unite(cor_between, c("feature_1", "feature_2"), sep = " X ")               # unite 2 columns to x name from plot
  }else df <- df %>% dplyr::rename(cor_between = Variable)                       # change Variable to x name from plot
  
  df %>%
    ggpubr::ggdotchart(x = "cor_between", y = "correlation",
                       color = "p.signif",                                       # Color by sig
                       #   palette = c("#00AFBB", "#E7B800", "#FC4E07"),         # Custom color palette
                       sorting = "descending",                                   # Sort value in descending order
                       add = "segments",                                         # Add segments from y = 0 to dots
                       add.params = list(color = "lightgray", size = 2),         # Change segment color and size
                       group = "p.signif",                                       # Order by groups
                       dot.size = 8,                                             # Large dot size
                       xlab = "",
                       rotate = TRUE,                                            # Rotate vertically
                       label = round(.$correlation, 1),                          # Add mpg values as dot labels
                       font.label = list(color = "white", size = 9, 
                                         vjust = 0.5),                           # Adjust label parameters
                       ggtheme = dtoplot_theme) +                                # ggplot2 theme
    dotplotcor_scale_fill() +                                            # Fix colors to signif factor levels even if missing
    geom_hline(yintercept = 0, linetype = 2, color = "lightgray")
}

  
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for Pre-Post Plots, t Change and ANCOVA Post
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Func t test si boxplot simplu
func_t_box <- function(df, ind, pre_var, post_var, test_method = "t.test"){
  df_modif <-
    df %>%
    select(ind, pre_var, post_var) %>% 
    tidyr::drop_na() %>%
    gather(pre_var, post_var, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), funs(as.factor)) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var, post_var))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = test_method, paired = TRUE)
  
  stat_comp2 <-
    df_modif %>% 
    do(tidy(t.test(.$value ~ .$Cond,
                   paired = TRUE,
                   data=.)))
  
  plot <- 
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07"), legend = "none") +
      stat_summary(fun.data = mean_se,  colour = "darkred") +
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label.x = as.numeric(df_modif$Cond)-0.4, label.y = max(df_modif$value)+0.5) + 
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", comparisons = list(c(pre_var, post_var)))
  
  cat(paste0("#### ", pre_var, " ", post_var, "\n", "\n"))
  print(stat_comp)
  print(stat_comp2)
  print(plot)
}


func_ancova_multibox <- function(df, ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2){
  
  diff_score_c1 <- paste0(post_var_c1, " - ", pre_var_c1)
  diff_score_c2 <- paste0(post_var_c2, " - ", pre_var_c2)
  
  ## Plots and p-values for t tests
  df_modif <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>% 
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), funs(as.factor)) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = "t.test", paired = TRUE, p.adjust.method = "holm")
  
  plot <-
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07", "#00AFBB", "#FC4E07"), legend = "none") +
    stat_summary(fun.data = mean_se,  colour = "darkred") +
    ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", 
                               label.y = c(max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           seq(max(df_modif$value) + 0.3*IQR(df_modif$value), 
                                               max(df_modif$value) + 0.9*IQR(df_modif$value), length.out = 4)),  
                               comparisons = list(c(pre_var_c1, post_var_c1),
                                                  c(pre_var_c2, post_var_c2),
                                                  c(post_var_c1, pre_var_c2),
                                                  c(pre_var_c1, pre_var_c2),
                                                  c(post_var_c1, post_var_c2),
                                                  c(pre_var_c1, post_var_c2)))
  
  ## For ttestChange or ANCOVAChange - we do ttestChange (Post-Pre) here, but it isnt very important
  df_modif2 <-                                 
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() 
  df_modif2[diff_score_c1] <- df_modif2[, post_var_c1] - df_modif2[, pre_var_c1]
  df_modif2[diff_score_c2] <- df_modif2[, post_var_c2] - df_modif2[, pre_var_c2]
  
  tChange <- t.test(df_modif2[, diff_score_c1], df_modif2[, diff_score_c2], paired = TRUE)
  
  ## For descriptives by 2 factors (PrePost and PozNeg)
  df_modif3 <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>%
    mutate(PrePost = case_when(stringr::str_detect(.$"Cond", "pre|Pre") ~ "Pre",
                               stringr::str_detect(.$"Cond", "post|Post") ~ "Post",
                               TRUE ~ NA_character_),
           PozNeg = case_when(stringr::str_detect(.$"Cond", "poz|Poz") ~ "Poz",
                              stringr::str_detect(.$"Cond", "neg|Neg") ~ "Neg",
                              TRUE ~ NA_character_)) %>%
    mutate(PrePost = as.factor(PrePost),
           PozNeg = as.factor(PozNeg))
  
  ## For ANCOVAPost - this is what we use
  df_modif4 <-
    df_modif3 %>%
    select(-"Cond") %>%
    spread("PrePost", "value")
  
  ## Models (here we use ANCOVAPost)    # https://m-clark.github.io/docs/mixedModels/anovamixed.html#introduction
  full_ancovaPost <-                                          # this is better than using lm() and glht()
      jmv::ancova(
        formula = Post ~ Pre + PozNeg,
        data = df_modif4,
        homo = TRUE,
        ss = "3",                                                     
        postHoc = ~ PozNeg,
        postHocCorr = list("tukey"),
        effectSize = list("eta", "partEta")
      )
  
      # mod_ancovaPost <- lm(Post ~ Pre + PozNeg, data = df_modif4)            # this is a Covariate Second model
      # mod_ancovaPost_ss3 <- car::Anova(mod_ancovaPost, type = "III")         # Type III sums of squares; see Andy Fields 2012
      # postHocs <- multcomp::glht(mod_ancovaPost, linfct = multcomp::mcp(PozNeg = "Tukey"))  # differences between the adjusted means,
      # sum_postHocs <- summary(postHocs)                                               # use Tukey or Dunnett?s post hoc tests
      # conf_postHocs <- confint(postHocs)
  scatter <-                                                             # Check for homogeneity of regression slopes
    ggplot(df_modif4, aes(Pre, Post, colour = PozNeg)) +
    geom_point(aes(shape = PozNeg), size = 3) +
    geom_smooth(method = "lm", aes(fill = PozNeg), alpha = 0.1)
    
  
  ## Other Models that work for this date
  # mod_ancovaPost <- lm(post ~ pre + treat)      # exactly the same with aov(post ~ pre + treat)
  # summary(mod_ancovaPost)
  # 
  # mod_anovaRM <- aov(score ~ treat*time + Error(id), dflong)
  # summary(mod_anovaRM)
  # 
  # mod_lme <- lme4::lmer(score ~ treat*time + (1|id), data=dflong)
  # anova(lmeModel)
  
  ## Output
  print(plot)
  cat(paste0("#### ", pre_var_c1, " ", post_var_c1, " ", pre_var_c2, " ", post_var_c2, "\n", "\n"))
  
  cat("#### Descriptives")
  psych::describeBy(df_modif3[, "value"], list(df_modif3[, "PrePost"], df_modif3[, "PozNeg"]), mat = TRUE) %>% 
    as.tibble() %>%
    print()
  cat("\n")
  
  print(stat_comp)
  cat("\n")
  
  cat("#### t Change")
  tidy(tChange) %>% print()
  cat("\n")
  
  cat("#### ANCOVA Post")
  cat("\n")
  cat("##### Homogeneity test")
  print(tibble::as.tibble(full_ancovaPost$assump$homo))
  cat("##### ANCOVA output")
  print(tibble::as.tibble(full_ancovaPost$main))
  # tidy(mod_ancovaPost) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  # cat("\n")
  cat("##### Post Hoc")
  print(tibble::as.tibble(full_ancovaPost$postHoc[[1]]))
  # tidy(sum_postHocs) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  cat("\n")
  cat("##### Homogeneity of regression slopes")
  subchunkify(plot(scatter), 5, 5)
}

4 Descriptives - Gen Varsta


        F         M 
0.7333333 0.2666667 
cannot compute exact p-value with ties

 Descriptive statistics by group 
group: F
------------------------------------------------------------------------------------------------------------- 
group: M

5 Analyses

5.1 Correlations between Diffrence Scores with other variables

5.1.0.1 Correlations with D_Ox_Poz

as.tibble() is deprecated, use as_tibble() (but mind the new semantics). This warning is displayed once per session.

5.1.0.2 Correlations with D_Ox_Neg

5.1.0.3 Correlations with D_Cort_Poz

5.1.0.4 Correlations with D_Cort_Neg

5.1.0.5 Correlations with D_VasS_Poz

5.1.0.6 Correlations with D_VasS_Neg

5.1.0.7 Correlations with D_VasB_Poz

5.1.0.8 Correlations with D_VasB_Neg

5.1.0.9 Correlations with D_IOS_Poz

5.1.0.10 Correlations with D_IOS_Neg

5.1.0.11 Correlations with D_DG_Poz

5.1.0.12 Correlations with D_DG_Neg

5.1.0.13 Correlations with D_TrustMin_Poz

5.1.0.14 Correlations with D_TrustMin_Neg

5.1.0.15 Correlations with D_TrustTot_Poz

5.1.0.16 Correlations with D_TrustTot_Neg

5.3 Simple before-after analyses with t test by Gender

5.3.1 Females

funs() is soft deprecated as of dplyr 0.8.0 Please use a list of either functions or lambdas:

# Simple named list: list(mean = mean, median = median)

# Auto named with tibble::lst(): tibble::lst(mean, median)

# Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE)) This warning is displayed once per session.#### Ox_pre_Poz Ox_post_Poz

5.3.1.1 Ox_pre_Neg Ox_post_Neg

5.3.1.2 VasS_prePoz VasS_postPoz

5.3.1.3 VasS_preNeg VasS_postNeg

5.3.1.4 VasB_prePoz VasB_postPoz

5.3.1.5 VasB_preNeg VasB_postNeg

5.3.1.6 IOS_prePoz IOS_postPoz

5.3.1.7 IOS_preNeg IOS_postNeg

5.3.1.8 DG_prePozTot DG_postPozTot

5.3.1.9 DG_preNegTot DG_postNegTot

5.3.1.10 TrustMinPozPre TrustMinPozPost

5.3.1.11 TrustMinNegPre TrustMinNegPost

5.3.1.12 TrustTotPozPre TrustTotPozPost

5.3.1.13 TrustTotNegPre TrustTotNegPost

–>

6 Session Info

R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)

Matrix products: default

locale:
[1] LC_COLLATE=Romanian_Romania.1250  LC_CTYPE=Romanian_Romania.1250    LC_MONETARY=Romanian_Romania.1250 LC_NUMERIC=C                     
[5] LC_TIME=Romanian_Romania.1250    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] rio_0.5.16         plyr_1.8.4         summarytools_0.8.8 DT_0.5             ggpubr_0.2         magrittr_1.5       broom_0.5.2       
 [8] papaja_0.1.0.9842  psych_1.8.12       forcats_0.4.0      stringr_1.4.0      dplyr_0.8.3        purrr_0.3.2        readr_1.3.1       
[15] tidyr_1.0.0        tibble_2.1.3       ggplot2_3.2.1      tidyverse_1.2.1    pacman_0.5.1      

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.2         lubridate_1.7.4    lattice_0.20-38    assertthat_0.2.1   zeallot_0.1.0      digest_0.6.21      R6_2.4.0          
 [8] cellranger_1.1.0   backports_1.1.4    httr_1.4.0         pillar_1.4.2       rlang_0.4.0        curl_3.2           lazyeval_0.2.2    
[15] readxl_1.1.0       data.table_1.11.8  rstudioapi_0.8     labeling_0.3       foreign_0.8-71     pander_0.6.3       htmlwidgets_1.3   
[22] RCurl_1.95-4.11    munsell_0.5.0      compiler_3.6.1     modelr_0.1.5       xfun_0.9           pkgconfig_2.0.3    mnormt_1.5-5      
[29] htmltools_0.3.6    tidyselect_0.2.5   codetools_0.2-16   matrixStats_0.54.0 crayon_1.3.4       withr_2.1.2        bitops_1.0-6      
[36] grid_3.6.1         nlme_3.1-140       jsonlite_1.6       gtable_0.3.0       lifecycle_0.1.0    scales_1.0.0       zip_1.0.0         
[43] cli_1.1.0          stringi_1.4.3      ggsignif_0.4.0     pryr_0.1.4         xml2_1.2.0         ellipsis_0.3.0     rapportools_1.0   
[50] generics_0.0.2     vctrs_0.2.0        openxlsx_4.1.0     tools_3.6.1        glue_1.3.1         hms_0.5.1          parallel_3.6.1    
[57] colorspace_1.4-1   rvest_0.3.2        knitr_1.25         haven_2.1.1       
 

A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gTy4yIFJlcG9ydCAtIEdlbmRlciIgDQpzdWJ0aXRsZTogIkZvY3VzIG9uIE9YVCBieSBHZW5kZXIiDQphdXRob3I6ICI8YnI+IENsYXVkaXUgUGFwYXN0ZXJpIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJW0gJVknKWAiDQpvdXRwdXQ6IA0KICAgIGh0bWxfbm90ZWJvb2s6DQogICAgICAgICAgIyBzZWxmX2NvbnRhaW5lZDogbm8NCiAgICAgICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgdGhlbWU6IHNwYWNlbGFiDQogICAgICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWwNCiAgICAgICAgICAgIGZpZ193aWR0aDogMTANCiAgICAgICAgICAgIGZpZ19oZWlnaHQ6IDkNCiAgICAgIyBwZGZfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgIyBmb250c2l6ZTogMTFwdA0KICAgICAgICAgICAgIyBnZW9tZXRyeTogbWFyZ2luPTFpbg0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDcNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNg0KICAgICAgICAgICAgIyBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgICMgZ2l0aHViX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyBodG1sX3ByZXZpZXc6IGZhbHNlDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNQ0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA1DQogICAgICAgICAgICAjIGRldjoganBlZw0KLS0tDQoNCg0KPCEtLSBTZXR1cCAtLT4NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMga2ludHIgb3B0aW9ucw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb21tZW50ID0gIiMiLA0KICBjb2xsYXBzZSA9IFRSVUUsDQogIGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gVFJVRSwgbWVzc2FnZSA9IFRSVUUsIGNhY2hlID0gVFJVRSAgICAgICAjIGVjaG8gPSBGYWxzZSBmb3IgZ2l0aHViX2RvY3VtZW50LCBidXQgd2lsbCBiZSBmb2xkZWQgaW4gaHRtbF9ub3RlYm9vaw0KKQ0KDQojIEdlbmVyYWwgUiBvcHRpb25zIGFuZCBpbmZvDQpzZXQuc2VlZCgxMTEpICAgICAgICAgICAgICAgIyBpbiBjYXNlIHdlIHVzZSByYW5kb21pemVkIHByb2NlZHVyZXMgICAgICAgDQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgICAgICAgIyBwb3NpdGl2ZSB2YWx1ZXMgYmlhcyB0b3dhcmRzIGZpeGVkIGFuZCBuZWdhdGl2ZSB0b3dhcmRzIHNjaWVudGlmaWMgbm90YXRpb24NCg0KIyBMb2FkIHBhY2thZ2VzDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFja2FnZXMgPC0gYygNCiAgInRpZHl2ZXJzZSIsICAgICAgIyBiZXN0IHRoaW5nIHRoYXQgaGFwcGVuZCB0byBtZQ0KICAicHN5Y2giLCAgICAgICAgICAjIGdlbmVyYWwgcHVycG9zZSB0b29sYm94IGZvciBwZXJzb25hbGl0eSwgcHN5Y2hvbWV0cmljIHRoZW9yeSBhbmQgZXhwZXJpbWVudGFsIHBzeWNob2xvZ3kNCiAgInBhcGFqYSIsICAgICAgICAgIyBmb3IgQVBBIHN0eWxlDQogICJicm9vbSIsICAgICAgICAgICMgZm9yIHRpZHkgbW9kZWxsaW5nDQogICJnZ3Bsb3QyIiwgICAgICAgICMgYmVzdCBwbG90cw0KICAiZ2dwdWJyIiwgICAgICAgICAjIGdncGxvdDIgdG8gcHVibGljYXRpb24gcXVhbGl0eQ0KICAiRFQiLCAgICAgICAgICAgICAjIG5pY2Ugc2VhcmNoYWJsZSBhbmQgZG93bmxvYWRhYmxlIHRhYmxlcw0KICAic3VtbWFyeXRvb2xzIiwNCiAgInBseXIiLCANCiAgInJpbyINCiAgIyAsIC4uLg0KKQ0KaWYgKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCnBhY21hbjo6cF9sb2FkKGNoYXIgPSBwYWNrYWdlcykNCg0KIyBUaGVtZXMgZm9yIGdncGxvdDIgcGxvdGluZyAoaGVyZSB1c2VkIEFQQSBzdHlsZSkNCnRoZW1lX3NldCh0aGVtZV9hcGEoKSkNCmBgYA0KDQoNCg0KPCEtLSBSZXBvcnQgLS0+DQoNCg0KIyBSZWFkIGFuZCBNZXJnZQ0KDQoNCmBgYHtyIHJlYWRfbWVyZ2UsIHJlc3VsdHM9J2FzaXMnfQ0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBSZWFkIGFuZCBNZXJnZQ0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0Kd2QgPC0gIkU6L0NpbmV0aWMgaWRlaSBub2kvRVhQRVJJTUVOVEUgT0dMIEZyb250aWVycyAoTy4yICYgTy4wLjMgJiBPLjAuMikiDQpzZXR3ZCh3ZCkNCg0KRGF0YVRydXN0IDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aCh3ZCwgIk8uMiBSRVpVTFRBVEVcXE8uMiBEYXRlIFByZWx1Y3JhcmVTUFNTIGN1IE5FTyBzaSBTVEFJIiwgIk8uMiBEYXRlIHB0IFRydXN0IEJVTiBjdSBORU8gc2kgU1RBSVkueGxzeCIpKQ0KRGF0YURHIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aCh3ZCwgIk8uMiBSRVpVTFRBVEVcXE8uMiBEYXRlIFByZWx1Y3JhcmVTUFNTIGN1IE5FTyBzaSBTVEFJIiwgIk8uMiBEYXRlIHB0IERHIEJVTiBjdSBORU8gc2kgU1RBSVkueGxzeCIpKQ0KRGF0YVZBUyA8LSByaW86OmltcG9ydChmaWxlLnBhdGgod2QsICJPLjIgUkVaVUxUQVRFXFxPLjIgVkFTLElPUyIsICJPLjIgRGF0ZSBQcmVsdWNyYXJlU1BTUy54bHN4IikpDQpEYXRhQklPIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aCh3ZCwgIk8uMiBCSU8iLCAiTy4yIE94IHNpIENvcnRpem9sLnhsc3giKSkNCiAgDQpEYXRhX21lcmdlMSA8LSBtZXJnZShEYXRhVkFTLCBEYXRhVHJ1c3QpICANCkRhdGFfbWVyZ2UyIDwtIG1lcmdlKERhdGFfbWVyZ2UxLCBEYXRhREcpIA0KRGF0YV9tZXJnZTMgPC0gbWVyZ2UoRGF0YV9tZXJnZTIsIERhdGFCSU8pDQoNCkRhdGEgPC0gRGF0YV9tZXJnZTMNCg0KdGVzdF9uYW1lcyA8LSB1bmlxdWUodW5saXN0KGxhcHBseShsaXN0KERhdGFUcnVzdCwgRGF0YURHLCBEYXRhVkFTLCBEYXRhQklPKSwgbmFtZXMpKSkNCm1lcmdlX25hbWVzIDwtIG5hbWVzKERhdGEpDQoNCmlmKGlkZW50aWNhbChtZXJnZV9uYW1lc1tvcmRlcihtZXJnZV9uYW1lcyldLCB0ZXN0X25hbWVzW29yZGVyKHRlc3RfbmFtZXMpXSkpeyAgICAjIHRoZSBvcmRlciBtYXR0ZXJzIGluIGlkZW50aWNhbCgpDQogIGNhdCgiKipNZXJnZSB3YXMgc3VjY2VzZnVsKioiKQ0KICBybSgiRGF0YV9tZXJnZTEiLCAiRGF0YV9tZXJnZTIiLCAiRGF0YV9tZXJnZTMiLCAiRGF0YUJJTyIsICJEYXRhREciLCAiRGF0YVRydXN0IiwgIkRhdGFWQVMiLCAidGVzdF9uYW1lcyIsICJtZXJnZV9uYW1lcyIpDQp9ZWxzZSBjYXQoIioqTWVyZ2UgdW5zdWNjZXNmdWwqKiIpIA0KDQoNCiMgR2VuZGVyIERhdGFmcmFtZQ0KRGF0YV9HZW4gPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiR2VuIHZhcnN0YSBPMDMgTzAyIE8yLnhsc3giKSwgd2hpY2ggPSAiTy4yIikNCg0KRGF0YV9HZW5fbWVyZ2VkIDwtIA0KICBEYXRhICU+JQ0KICB0aWR5cjo6c2VwYXJhdGUoSW5kaWNhdGl2LCAgYygiSURfdGFnIiwgIklEIiwgInN0dWR5X3RhZyIpLCAiXFxzKyIpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHNwbGl0IG9uIHdoaXRlIHNwYWNlDQogIHNlbGVjdCgtYygiSURfdGFnIiwgInN0dWR5X3RhZyIpKSAlPiUNCiAgbXV0YXRlKElEID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoSUQpKSkgJT4lDQogIGRwbHlyOjpsZWZ0X2pvaW4oLiwgRGF0YV9HZW4sIGJ5ID0gYygiSUQiKSkgJT4lDQogIHNlbGVjdCgxOjcsIEdlbiwgVmFyc3RhLCBldmVyeXRoaW5nKCkpDQoNCkRhdGFfZmVtIDwtIA0KICBEYXRhX0dlbl9tZXJnZWQgJT4lDQogIGZpbHRlcihHZW4gPT0gIkYiKQ0KDQpEYXRhX21hc2MgPC0gDQogIERhdGFfR2VuX21lcmdlZCAlPiUNCiAgZmlsdGVyKEdlbiA9PSAiTSIpDQpgYGANCg0KDQojIERlcml2ZSBuZXcgdmFyaWFibGVzDQoNCmBgYHtyIGRlcml2ZV92YXIsIGhpZGU9VFJVRX0NCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgRGVyaXZlIG5ldyB2YXJpYWJsZXMNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCkRhdGEkRF9WYXNTX1BveiA8LSBEYXRhWywgIlZhc1NfcG9zdFBveiJdIC0gRGF0YVssICJWYXNTX3ByZVBveiJdIA0KRGF0YSREX1Zhc1NfTmVnIDwtIERhdGFbLCAiVmFzU19wb3N0TmVnIl0gLSBEYXRhWywgIlZhc1NfcHJlTmVnIl0NCkRhdGEkRF9WYXNCX1BveiA8LSBEYXRhWywgIlZhc0JfcG9zdFBveiJdIC0gRGF0YVssICJWYXNCX3ByZVBveiJdIA0KRGF0YSREX1Zhc0JfTmVnIDwtIERhdGFbLCAiVmFzQl9wb3N0TmVnIl0gLSBEYXRhWywgIlZhc0JfcHJlTmVnIl0NCkRhdGEkRF9JT1NfUG96IDwtIERhdGFbLCAiSU9TX3Bvc3RQb3oiXSAtIERhdGFbLCAiSU9TX3ByZVBveiJdIA0KRGF0YSREX0lPU19OZWcgPC0gRGF0YVssICJJT1NfcG9zdE5lZyJdIC0gRGF0YVssICJJT1NfcHJlTmVnIl0NCg0KRGF0YSREX1NhbTFfUG96IDwtIERhdGFbLCAiU2FtMV9wb3N0UG96Il0gLSBEYXRhWywgIlNhbTFfcHJlUG96Il0gDQpEYXRhJERfU2FtMV9OZWcgPC0gRGF0YVssICJTYW0xX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtMV9wcmVOZWciXQ0KRGF0YSREX1NhbTJfUG96IDwtIERhdGFbLCAiU2FtMl9wb3N0UG96Il0gLSBEYXRhWywgIlNhbTJfcHJlUG96Il0gDQpEYXRhJERfU2FtMl9OZWcgPC0gRGF0YVssICJTYW0yX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtMl9wcmVOZWciXQ0KRGF0YSREX1NhbTNfUG96IDwtIERhdGFbLCAiU2FtM19wb3N0UG96Il0gLSBEYXRhWywgIlNhbTNfcHJlUG96Il0gDQpEYXRhJERfU2FtM19OZWcgPC0gRGF0YVssICJTYW0zX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtM19wcmVOZWciXQ0KDQpEYXRhJERfREdfUG96IDwtIERhdGFbLCAiREdfcG9zdFBvelRvdCJdIC0gRGF0YVssICJER19wcmVQb3pUb3QiXSANCkRhdGEkRF9ER19OZWcgPC0gRGF0YVssICJER19wb3N0TmVnVG90Il0gLSBEYXRhWywgIkRHX3ByZU5lZ1RvdCJdDQoNCkRhdGEkRF9UcnVzdE1pbl9Qb3ogPC0gRGF0YVssICJUcnVzdE1pblBvelBvc3QiXSAtIERhdGFbLCAiVHJ1c3RNaW5Qb3pQcmUiXSANCkRhdGEkRF9UcnVzdE1pbl9OZWcgPC0gRGF0YVssICJUcnVzdE1pbk5lZ1Bvc3QiXSAtIERhdGFbLCAiVHJ1c3RNaW5OZWdQcmUiXQ0KRGF0YSREX1RydXN0VG90X1BveiA8LSBEYXRhWywgIlRydXN0VG90UG96UG9zdCJdIC0gRGF0YVssICJUcnVzdFRvdFBvelByZSJdIA0KRGF0YSREX1RydXN0VG90X05lZyA8LSBEYXRhWywgIlRydXN0VG90TmVnUG9zdCJdIC0gRGF0YVssICJUcnVzdFRvdE5lZ1ByZSJdDQoNCkRhdGEkRF9Db3J0X1BveiA8LSBEYXRhWywgIkNvcnRfcG9zdF9Qb3oiXSAtIERhdGFbLCAiQ29ydF9wcmVfUG96Il0gDQpEYXRhJERfQ29ydF9OZWcgPC0gRGF0YVssICJDb3J0X3Bvc3RfTmVnIl0gLSBEYXRhWywgIkNvcnRfcHJlX05lZyJdDQpEYXRhJERfT3hfUG96IDwtIERhdGFbLCAiT3hfcG9zdF9Qb3oiXSAtIERhdGFbLCAiT3hfcHJlX1BveiJdIA0KRGF0YSREX094X05lZyA8LSBEYXRhWywgIk94X3Bvc3RfTmVnIl0gLSBEYXRhWywgIk94X3ByZV9OZWciXQ0KYGBgDQoNCg0KIyBEZWZpbmUgRnVuY3Rpb25zIA0KDQpgYGB7ciBkZWZfZnVuY19zdWJjaHVua3Bsb3QsIGhpZGU9VFJVRX0NCnN1YmNodW5raWZ5IDwtIGZ1bmN0aW9uKGcsIGZpZ19oZWlnaHQ9NywgZmlnX3dpZHRoPTUpIHsNCiAgZ19kZXBhcnNlZCA8LSBwYXN0ZTAoZGVwYXJzZSgNCiAgICBmdW5jdGlvbigpIHtnfQ0KICApLCBjb2xsYXBzZSA9ICcnKQ0KICANCiAgc3ViX2NodW5rIDwtIHBhc3RlMCgiDQogIGAiLCJgYHtyIHN1Yl9jaHVua18iLCBmbG9vcihydW5pZigxKSAqIDEwMDAwKSwgIiwgZmlnLmhlaWdodD0iLCBmaWdfaGVpZ2h0LCAiLCBmaWcud2lkdGg9IiwgZmlnX3dpZHRoLCAiLCBlY2hvPUZBTFNFfSIsDQogICJcbigiLCANCiAgICBnX2RlcGFyc2VkDQogICAgLCAiKSgpIiwNCiAgIlxuYCIsImBgDQogICIpDQogIA0KICBjYXQoa25pdHI6OmtuaXQodGV4dCA9IGtuaXRyOjprbml0X2V4cGFuZCh0ZXh0ID0gc3ViX2NodW5rKSwgcXVpZXQgPSBUUlVFKSkNCn0NCmBgYA0KDQpgYGB7ciBkZWZfZnVuYywgaGlkZT1UUlVFfQ0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBEZWZpbmUgRnVuY3Rpb24gZm9yIG1pbmluZyBjb3JyZWxhdGlvbnMNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMjIEZ1bmN0aW9uIGZvciBwLXZhbHVlIHNpZ25pZmljYW5jZSAtLSBib3RoIGZvciBmdW5jX2FuY292YV9tdWx0aWJveCgpLCBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoKSBhbmQgQ29ycmVsYXRpb25zX1dpdGhfT25lKCkNCnN0YXJzX3NpZ25pZiA8LSBmdW5jdGlvbihwdmFsKSB7DQogIHN0YXJzID0gIm5zIg0KICBpZihwdmFsIDw9IDAuMDAxKQ0KICAgIHN0YXJzID0gIioqKiINCiAgaWYocHZhbCA+IDAuMDAxICYgcHZhbCA8PSAwLjAxKQ0KICAgIHN0YXJzID0gIioqIg0KICBpZihwdmFsID4gMC4wMSAmIHB2YWwgPD0gMC4wNSkNCiAgICBzdGFycyA9ICIqIg0KICBpZihwdmFsID4gMC4wNSAmIHB2YWwgPD0gMC4xKQ0KICAgIHN0YXJzID0gIi4iDQogIHN0YXJzDQp9DQoNCiMjIEZ1bmN0aW9uIHRoYXQgcmV0dXJucyBjb3JyZWxhdGlvbnMgb2YgYWxsIHZhcmlhYmxlcyBpbiBkZXNjZW5kaW5nIG9yZGVyLg0KIyBBcmcgZm9yIHRocmVzaG9sZCB3aXRoIGRlZmF1bHQgYXQgLjMgd2lsbCBrZWVwIG9ubHkgY29ycmVsYW50aW9ucyBhYm92ZSAuMyBhbmQgYmVsb3cgLS4zLiBBbHNvIGhhcyB0aHJlc2hob2xkIGZvciBwLXZhbHVlLiANCkdldF9Ub3BfUmVsYXRpb25zaGlwcyA8LSBmdW5jdGlvbihkYXRhX3NldCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZD0wLjMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlX3RocmVzaG9sZD0wLjA1KSB7DQogIHJlcXVpcmUocHN5Y2gpDQogIHJlcXVpcmUoZHBseXIpDQogIGZlYXR1cmVfbmFtZXMgPC0gbmFtZXMoZGF0YV9zZXQpDQogICMgc3RyaXAgdmFyIG5hbWVzIHRvIGluZGV4IGZvciBwYWlyLXdpc2UgaWRlbnRpZmljYXRpb24NCiAgbmFtZXMoZGF0YV9zZXQpIDwtIHNlcSgxOm5jb2woZGF0YV9zZXQpKQ0KICAjIGNhbGN1bGF0ZSBjb3JyZWxhdGlvbiBhbmQgc2lnbmlmaWNhbmNlIG51bWJlcnMNCiAgY29yX2RhdGFfZGYgPC0gcHN5Y2g6OmNvcnIudGVzdChkYXRhX3NldCkNCiAgIyBhcHBseSB2YXIgbmFtZXMgdG8gY29ycmVsYXRpb24gbWF0cml4IG92ZXIgaW5kZXgNCiAgcm93bmFtZXMoY29yX2RhdGFfZGYkcikgPC0gZmVhdHVyZV9uYW1lcw0KICBjb2xuYW1lcyhjb3JfZGF0YV9kZiRyKSA8LSBmZWF0dXJlX25hbWVzDQogICMgdG9wIGNvciBhbmQgc2lnDQogIHJlbGF0aW9uc2hpcHNfc2V0IDwtIGNvcl9kYXRhX2RmJGNpWyxjKCdyJywncCcpXQ0KICAjIGFwcGx5IHZhciBuYW1lcyB0byBkYXRhIG92ZXIgaW5kZXggcGFpcnMNCiAgcmVsYXRpb25zaGlwc19zZXQkZmVhdHVyZV8xIDwtIGZlYXR1cmVfbmFtZXNbYXMubnVtZXJpYyhzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocmVsYXRpb25zaGlwc19zZXQpLCAiLSIpLCBgW2AsIDEpKV0NCiAgcmVsYXRpb25zaGlwc19zZXQkZmVhdHVyZV8yIDwtIGZlYXR1cmVfbmFtZXNbYXMubnVtZXJpYygNCiAgICBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocmVsYXRpb25zaGlwc19zZXQpLCAiLSIpLCBgW2AsIDIpKV0NCiAgcmVsYXRpb25zaGlwc19zZXQgPC0gZHBseXI6OnNlbGVjdChyZWxhdGlvbnNoaXBzX3NldCwgZmVhdHVyZV8xLCBmZWF0dXJlXzIsIHIsIHApICU+JSBkcGx5cjo6cmVuYW1lKGNvcnJlbGF0aW9uID0gciwgcC52YWx1ZSA9IHApDQogICMgcmV0dXJuIG9ubHkgdGhlIG1vc3QgaW5zdGVyZXN0aW5nIHJlbGF0aW9uc2hpcHMNCiAgcmV0dXJuKGZpbHRlcihyZWxhdGlvbnNoaXBzX3NldCwgYWJzKGNvcnJlbGF0aW9uKSA+IGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgJg0KICAgICAgICAgICAgICAgICAgcC52YWx1ZSA8IHB2YWx1ZV90aHJlc2hvbGQpICU+JSANCiAgICAgICAgYXJyYW5nZShwLnZhbHVlKSAlPiUNCiAgICAgICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpKQ0KfQ0KDQojIyBGdW5jdGlvbiB0aGF0IHJldHVybnMgYWxsIGNvcnJlbGF0aW9uIGJldHdlZW4gbnVtZXJpYyB2YXJpYWJsZXMgYW5kIG9uZSBzcGVjaWZpYyB2YXJpYWJsZQ0KQ29ycmVsYXRpb25zX1dpdGhfT25lIDwtIGZ1bmN0aW9uKGRhdGFfc2V0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQ9MC4zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZV90aHJlc2hvbGQ9MC4wNSkgew0KICByZXF1aXJlKHBzeWNoKQ0KICByZXF1aXJlKGRwbHlyKQ0KICAjIHVzZSBhbGwgbnVtZXJpYyBjb2x1bW5zIG9ubHkNCiAgbnVtZXJpY19jb2xzIDwtIHVubGlzdChsYXBwbHkoZGF0YV9zZXQsIGlzLm51bWVyaWMpKQ0KICBkYXRhX3NldCA8LSBkYXRhX3NldFssIG51bWVyaWNfY29sc10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICMgY2FsY3VsYXRlIGNvcnJlbGF0aW9uIGFuZCBzaWduaWZpY2FuY2UgbnVtYmVycw0KICBjb3JfZGF0YV9kZiA8LSBwc3ljaDo6Y29yci50ZXN0KGRhdGFfc2V0WywgbmFtZXMoZGF0YV9zZXQpICE9IHZhcmlhYmxlXSwgZGF0YV9zZXRbLCB2YXJpYWJsZV0sIG1pbmxlbmd0aCA9IDIwLCBhZGp1c3Q9Im5vbmUiKQ0KICAjIHRvcCBjb3IgYW5kIHNpZw0KICByZWxhdGlvbnNoaXBzX3NldCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGNvcl9kYXRhX2RmJHIsIGNvcl9kYXRhX2RmJHApKSAgICAgIyBzYW1lIGFzICBjb3JfZGF0YV9kZiRjaVssYygncicsJ3AnKV0NCiAgcmVsYXRpb25zaGlwc19zZXQgPC0gdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4ocmVsYXRpb25zaGlwc19zZXQsICJWYXJpYWJsZSIpICAgIyByZWxhdGlvbnNoaXBzX3NldCRWYXJpYWJsZSA8LSByb3duYW1lcyhyZWxhdGlvbnNoaXBzX3NldCkNCiAgY29sbmFtZXMocmVsYXRpb25zaGlwc19zZXQpIDwtIGMoIlZhcmlhYmxlIiwgImNvcnJlbGF0aW9uIiwgInAudmFsdWUiKQ0KICAjIHJldHVybiBvbmx5IHRoZSBtb3N0IGluc3RlcmVzdGluZyByZWxhdGlvbnNoaXBzDQogIGNhdCgiIyMjIyBDb3JyZWxhdGlvbnMgd2l0aCAiLCB2YXJpYWJsZSwgIlxuIikNCiAgcmV0dXJuKGZpbHRlcihyZWxhdGlvbnNoaXBzX3NldCwgYWJzKGNvcnJlbGF0aW9uKSA+IGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgJg0KICAgICAgICAgICAgICAgICAgcC52YWx1ZSA8IHB2YWx1ZV90aHJlc2hvbGQpICU+JSANCiAgICAgICAgICAgYXJyYW5nZShwLnZhbHVlKSAlPiUNCiAgICAgICAgICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpKSAlPiUNCiAgICAgICAgICAgdGliYmxlOjphcy50aWJibGUoKQ0KfSAgDQoNCg0KIyMgRnVuY3Rpb24gZm9yIHBsb3RpbmcgY29ycmVsYXRpb24gZGF0YSBmcmFtZXMgcmVzdWx0aW5nIGZyb20gR2V0X1RvcF9SZWxhdGlvbnNoaXBzIGFuZCBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoKQ0KZnVuY19kb3RwbG90X2NvciA8LSBmdW5jdGlvbihkZil7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaHR0cHM6Ly93d3cuci1wa2cub3JnL3BrZy9nZ3B1YnINCiAgZG90cGxvdGNvcl9zY2FsZV9maWxsIDwtIGZ1bmN0aW9uKC4uLil7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEZpeCBjb2xvcnMgdG8gc2lnbmlmIGZhY3RvciBsZXZlbHMgZXZlbiBpZiBtaXNzaW5nDQogICAgZ2dwbG90Mjo6Om1hbnVhbF9zY2FsZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgJ2NvbG9yJywgDQogICAgICB2YWx1ZXMgPSBzZXROYW1lcygNCiAgICAgICAgYygiZGFya2dyZWVuIiwgImdyZWVuMyIsICJsYXduZ3JlZW4iLCAieWVsbG93IiwgInJlZCIpLCANCiAgICAgICAgYygiKioqIiwgIioqIiwgIioiLCAiLiIsICJucyIpKSwgDQogICAgICAuLi4NCiAgICApDQogIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIA0KICBkdG9wbG90X3RoZW1lIDwtIA0KICAgIGdncHVicjo6dGhlbWVfcHVicigpICsNCiAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KICANCiAgaWYoISJWYXJpYWJsZSIgJWluJSBjb2xuYW1lcyhkZikpeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gb2RlciB0byB3b3JrIGZvciBib3RoIEdldF9Ub3BfUmVsYXRpb25zaGlwcyBhbmQgQ29ycmVsYXRpb25zX1dpdGhfT25lKCkNCiAgZGYgPC0gDQogICAgZGYgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgIHVuaXRlKGNvcl9iZXR3ZWVuLCBjKCJmZWF0dXJlXzEiLCAiZmVhdHVyZV8yIiksIHNlcCA9ICIgWCAiKSAgICAgICAgICAgICAgICMgdW5pdGUgMiBjb2x1bW5zIHRvIHggbmFtZSBmcm9tIHBsb3QNCiAgfWVsc2UgZGYgPC0gZGYgJT4lIGRwbHlyOjpyZW5hbWUoY29yX2JldHdlZW4gPSBWYXJpYWJsZSkgICAgICAgICAgICAgICAgICAgICAgICMgY2hhbmdlIFZhcmlhYmxlIHRvIHggbmFtZSBmcm9tIHBsb3QNCiAgDQogIGRmICU+JQ0KICAgIGdncHVicjo6Z2dkb3RjaGFydCh4ID0gImNvcl9iZXR3ZWVuIiwgeSA9ICJjb3JyZWxhdGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInAuc2lnbmlmIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENvbG9yIGJ5IHNpZw0KICAgICAgICAgICAgICAgICAgICAgICAjICAgcGFsZXR0ZSA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IiksICAgICAgICAgIyBDdXN0b20gY29sb3IgcGFsZXR0ZQ0KICAgICAgICAgICAgICAgICAgICAgICBzb3J0aW5nID0gImRlc2NlbmRpbmciLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBTb3J0IHZhbHVlIGluIGRlc2NlbmRpbmcgb3JkZXINCiAgICAgICAgICAgICAgICAgICAgICAgYWRkID0gInNlZ21lbnRzIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQWRkIHNlZ21lbnRzIGZyb20geSA9IDAgdG8gZG90cw0KICAgICAgICAgICAgICAgICAgICAgICBhZGQucGFyYW1zID0gbGlzdChjb2xvciA9ICJsaWdodGdyYXkiLCBzaXplID0gMiksICAgICAgICAgIyBDaGFuZ2Ugc2VnbWVudCBjb2xvciBhbmQgc2l6ZQ0KICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9ICJwLnNpZ25pZiIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBPcmRlciBieSBncm91cHMNCiAgICAgICAgICAgICAgICAgICAgICAgZG90LnNpemUgPSA4LCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTGFyZ2UgZG90IHNpemUNCiAgICAgICAgICAgICAgICAgICAgICAgeGxhYiA9ICIiLA0KICAgICAgICAgICAgICAgICAgICAgICByb3RhdGUgPSBUUlVFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSb3RhdGUgdmVydGljYWxseQ0KICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKC4kY29ycmVsYXRpb24sIDEpLCAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGQgbXBnIHZhbHVlcyBhcyBkb3QgbGFiZWxzDQogICAgICAgICAgICAgICAgICAgICAgIGZvbnQubGFiZWwgPSBsaXN0KGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDAuNSksICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGp1c3QgbGFiZWwgcGFyYW1ldGVycw0KICAgICAgICAgICAgICAgICAgICAgICBnZ3RoZW1lID0gZHRvcGxvdF90aGVtZSkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnZ3Bsb3QyIHRoZW1lDQogICAgZG90cGxvdGNvcl9zY2FsZV9maWxsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBGaXggY29sb3JzIHRvIHNpZ25pZiBmYWN0b3IgbGV2ZWxzIGV2ZW4gaWYgbWlzc2luZw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAibGlnaHRncmF5IikNCn0NCg0KICANCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgRGVmaW5lIEZ1bmN0aW9uIGZvciBQcmUtUG9zdCBQbG90cywgdCBDaGFuZ2UgYW5kIEFOQ09WQSBQb3N0DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIyBGdW5jIHQgdGVzdCBzaSBib3hwbG90IHNpbXBsdQ0KZnVuY190X2JveCA8LSBmdW5jdGlvbihkZiwgaW5kLCBwcmVfdmFyLCBwb3N0X3ZhciwgdGVzdF9tZXRob2QgPSAidC50ZXN0Iil7DQogIGRmX21vZGlmIDwtDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3ZhciwgcG9zdF92YXIpICU+JSANCiAgICB0aWR5cjo6ZHJvcF9uYSgpICU+JQ0KICAgIGdhdGhlcihwcmVfdmFyLCBwb3N0X3Zhciwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JSANCiAgICBtdXRhdGVfYXQodmFycyhjKDEsIDIpKSwgZnVucyhhcy5mYWN0b3IpKSAlPiUgDQogICAgbXV0YXRlKENvbmQgPSBmYWN0b3IoQ29uZCwgbGV2ZWxzID0gYyhwcmVfdmFyLCBwb3N0X3ZhcikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9IHRlc3RfbWV0aG9kLCBwYWlyZWQgPSBUUlVFKQ0KICANCiAgc3RhdF9jb21wMiA8LQ0KICAgIGRmX21vZGlmICU+JSANCiAgICBkbyh0aWR5KHQudGVzdCguJHZhbHVlIH4gLiRDb25kLA0KICAgICAgICAgICAgICAgICAgIHBhaXJlZCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgZGF0YT0uKSkpDQogIA0KICBwbG90IDwtIA0KICAgIGdncHVicjo6Z2dwYWlyZWQoZGZfbW9kaWYsIHggPSAiQ29uZCIsIHkgPSAidmFsdWUiLCBpZCA9IGluZCwgDQogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJDb25kIiwgbGluZS5jb2xvciA9ICJncmF5IiwgbGluZS5zaXplID0gMC40LA0KICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IGMoIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICAgIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsICBjb2xvdXIgPSAiZGFya3JlZCIpICsNCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbC54ID0gYXMubnVtZXJpYyhkZl9tb2RpZiRDb25kKS0wLjQsIGxhYmVsLnkgPSBtYXgoZGZfbW9kaWYkdmFsdWUpKzAuNSkgKyANCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbCA9ICJwLnNpZ25pZiIsIGNvbXBhcmlzb25zID0gbGlzdChjKHByZV92YXIsIHBvc3RfdmFyKSkpDQogIA0KICBjYXQocGFzdGUwKCIjIyMjICIsIHByZV92YXIsICIgIiwgcG9zdF92YXIsICJcbiIsICJcbiIpKQ0KICBwcmludChzdGF0X2NvbXApDQogIHByaW50KHN0YXRfY29tcDIpDQogIHByaW50KHBsb3QpDQp9DQoNCg0KZnVuY19hbmNvdmFfbXVsdGlib3ggPC0gZnVuY3Rpb24oZGYsIGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKXsNCiAgDQogIGRpZmZfc2NvcmVfYzEgPC0gcGFzdGUwKHBvc3RfdmFyX2MxLCAiIC0gIiwgcHJlX3Zhcl9jMSkNCiAgZGlmZl9zY29yZV9jMiA8LSBwYXN0ZTAocG9zdF92YXJfYzIsICIgLSAiLCBwcmVfdmFyX2MyKQ0KICANCiAgIyMgUGxvdHMgYW5kIHAtdmFsdWVzIGZvciB0IHRlc3RzDQogIGRmX21vZGlmIDwtDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSAlPiUgDQogICAgdGlkeXI6OmRyb3BfbmEoKSAlPiUNCiAgICBnYXRoZXIocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyLCBrZXkgPSAiQ29uZCIsIHZhbHVlID0gInZhbHVlIikgJT4lIA0KICAgIG11dGF0ZV9hdCh2YXJzKGMoMSwgMikpLCBmdW5zKGFzLmZhY3RvcikpICU+JSANCiAgICBtdXRhdGUoQ29uZCA9IGZhY3RvcihDb25kLCBsZXZlbHMgPSBjKHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIpDQogIA0KICBwbG90IDwtDQogICAgZ2dwdWJyOjpnZ3BhaXJlZChkZl9tb2RpZiwgeCA9ICJDb25kIiwgeSA9ICJ2YWx1ZSIsIGlkID0gaW5kLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIkNvbmQiLCBsaW5lLmNvbG9yID0gImdyYXkiLCBsaW5lLnNpemUgPSAwLjQsDQogICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiwgIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCAgY29sb3VyID0gImRhcmtyZWQiKSArDQogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsID0gInAuc2lnbmlmIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwueSA9IGMobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMSpJUVIoZGZfbW9kaWYkdmFsdWUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChkZl9tb2RpZiR2YWx1ZSkgKyAwLjEqSVFSKGRmX21vZGlmJHZhbHVlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXEobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMypJUVIoZGZfbW9kaWYkdmFsdWUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX21vZGlmJHZhbHVlKSArIDAuOSpJUVIoZGZfbW9kaWYkdmFsdWUpLCBsZW5ndGgub3V0ID0gNCkpLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbnMgPSBsaXN0KGMocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocHJlX3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocG9zdF92YXJfYzEsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMikpKQ0KICANCiAgIyMgRm9yIHR0ZXN0Q2hhbmdlIG9yIEFOQ09WQUNoYW5nZSAtIHdlIGRvIHR0ZXN0Q2hhbmdlIChQb3N0LVByZSkgaGVyZSwgYnV0IGl0IGlzbnQgdmVyeSBpbXBvcnRhbnQNCiAgZGZfbW9kaWYyIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSAlPiUNCiAgICB0aWR5cjo6ZHJvcF9uYSgpIA0KICBkZl9tb2RpZjJbZGlmZl9zY29yZV9jMV0gPC0gZGZfbW9kaWYyWywgcG9zdF92YXJfYzFdIC0gZGZfbW9kaWYyWywgcHJlX3Zhcl9jMV0NCiAgZGZfbW9kaWYyW2RpZmZfc2NvcmVfYzJdIDwtIGRmX21vZGlmMlssIHBvc3RfdmFyX2MyXSAtIGRmX21vZGlmMlssIHByZV92YXJfYzJdDQogIA0KICB0Q2hhbmdlIDwtIHQudGVzdChkZl9tb2RpZjJbLCBkaWZmX3Njb3JlX2MxXSwgZGZfbW9kaWYyWywgZGlmZl9zY29yZV9jMl0sIHBhaXJlZCA9IFRSVUUpDQogIA0KICAjIyBGb3IgZGVzY3JpcHRpdmVzIGJ5IDIgZmFjdG9ycyAoUHJlUG9zdCBhbmQgUG96TmVnKQ0KICBkZl9tb2RpZjMgPC0NCiAgICBkZiAlPiUNCiAgICBzZWxlY3QoaW5kLCBwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiwgcG9zdF92YXJfYzIpICU+JQ0KICAgIHRpZHlyOjpkcm9wX25hKCkgJT4lDQogICAgZ2F0aGVyKHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMiwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQ0KICAgIG11dGF0ZShQcmVQb3N0ID0gY2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiQ29uZCIsICJwcmV8UHJlIikgfiAiUHJlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KC4kIkNvbmQiLCAicG9zdHxQb3N0IikgfiAiUG9zdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgICBQb3pOZWcgPSBjYXNlX3doZW4oc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgInBvenxQb3oiKSB+ICJQb3oiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgIm5lZ3xOZWciKSB+ICJOZWciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8pKSAlPiUNCiAgICBtdXRhdGUoUHJlUG9zdCA9IGFzLmZhY3RvcihQcmVQb3N0KSwNCiAgICAgICAgICAgUG96TmVnID0gYXMuZmFjdG9yKFBvek5lZykpDQogIA0KICAjIyBGb3IgQU5DT1ZBUG9zdCAtIHRoaXMgaXMgd2hhdCB3ZSB1c2UNCiAgZGZfbW9kaWY0IDwtDQogICAgZGZfbW9kaWYzICU+JQ0KICAgIHNlbGVjdCgtIkNvbmQiKSAlPiUNCiAgICBzcHJlYWQoIlByZVBvc3QiLCAidmFsdWUiKQ0KICANCiAgIyMgTW9kZWxzIChoZXJlIHdlIHVzZSBBTkNPVkFQb3N0KSAgICAjIGh0dHBzOi8vbS1jbGFyay5naXRodWIuaW8vZG9jcy9taXhlZE1vZGVscy9hbm92YW1peGVkLmh0bWwjaW50cm9kdWN0aW9uDQogIGZ1bGxfYW5jb3ZhUG9zdCA8LSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhpcyBpcyBiZXR0ZXIgdGhhbiB1c2luZyBsbSgpIGFuZCBnbGh0KCkNCiAgICAgIGptdjo6YW5jb3ZhKA0KICAgICAgICBmb3JtdWxhID0gUG9zdCB+IFByZSArIFBvek5lZywNCiAgICAgICAgZGF0YSA9IGRmX21vZGlmNCwNCiAgICAgICAgaG9tbyA9IFRSVUUsDQogICAgICAgIHNzID0gIjMiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIHBvc3RIb2MgPSB+IFBvek5lZywNCiAgICAgICAgcG9zdEhvY0NvcnIgPSBsaXN0KCJ0dWtleSIpLA0KICAgICAgICBlZmZlY3RTaXplID0gbGlzdCgiZXRhIiwgInBhcnRFdGEiKQ0KICAgICAgKQ0KICANCiAgICAgICMgbW9kX2FuY292YVBvc3QgPC0gbG0oUG9zdCB+IFByZSArIFBvek5lZywgZGF0YSA9IGRmX21vZGlmNCkgICAgICAgICAgICAjIHRoaXMgaXMgYSBDb3ZhcmlhdGUgU2Vjb25kIG1vZGVsDQogICAgICAjIG1vZF9hbmNvdmFQb3N0X3NzMyA8LSBjYXI6OkFub3ZhKG1vZF9hbmNvdmFQb3N0LCB0eXBlID0gIklJSSIpICAgICAgICAgIyBUeXBlIElJSSBzdW1zIG9mIHNxdWFyZXM7IHNlZSBBbmR5IEZpZWxkcyAyMDEyDQogICAgICAjIHBvc3RIb2NzIDwtIG11bHRjb21wOjpnbGh0KG1vZF9hbmNvdmFQb3N0LCBsaW5mY3QgPSBtdWx0Y29tcDo6bWNwKFBvek5lZyA9ICJUdWtleSIpKSAgIyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBhZGp1c3RlZCBtZWFucywNCiAgICAgICMgc3VtX3Bvc3RIb2NzIDwtIHN1bW1hcnkocG9zdEhvY3MpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBUdWtleSBvciBEdW5uZXR0P3MgcG9zdCBob2MgdGVzdHMNCiAgICAgICMgY29uZl9wb3N0SG9jcyA8LSBjb25maW50KHBvc3RIb2NzKQ0KICBzY2F0dGVyIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ2hlY2sgZm9yIGhvbW9nZW5laXR5IG9mIHJlZ3Jlc3Npb24gc2xvcGVzDQogICAgZ2dwbG90KGRmX21vZGlmNCwgYWVzKFByZSwgUG9zdCwgY29sb3VyID0gUG96TmVnKSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUG96TmVnKSwgc2l6ZSA9IDMpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBhZXMoZmlsbCA9IFBvek5lZyksIGFscGhhID0gMC4xKQ0KICAgIA0KICANCiAgIyMgT3RoZXIgTW9kZWxzIHRoYXQgd29yayBmb3IgdGhpcyBkYXRlDQogICMgbW9kX2FuY292YVBvc3QgPC0gbG0ocG9zdCB+IHByZSArIHRyZWF0KSAgICAgICMgZXhhY3RseSB0aGUgc2FtZSB3aXRoIGFvdihwb3N0IH4gcHJlICsgdHJlYXQpDQogICMgc3VtbWFyeShtb2RfYW5jb3ZhUG9zdCkNCiAgIyANCiAgIyBtb2RfYW5vdmFSTSA8LSBhb3Yoc2NvcmUgfiB0cmVhdCp0aW1lICsgRXJyb3IoaWQpLCBkZmxvbmcpDQogICMgc3VtbWFyeShtb2RfYW5vdmFSTSkNCiAgIyANCiAgIyBtb2RfbG1lIDwtIGxtZTQ6OmxtZXIoc2NvcmUgfiB0cmVhdCp0aW1lICsgKDF8aWQpLCBkYXRhPWRmbG9uZykNCiAgIyBhbm92YShsbWVNb2RlbCkNCiAgDQogICMjIE91dHB1dA0KICBwcmludChwbG90KQ0KICBjYXQocGFzdGUwKCIjIyMjICIsIHByZV92YXJfYzEsICIgIiwgcG9zdF92YXJfYzEsICIgIiwgcHJlX3Zhcl9jMiwgIiAiLCBwb3N0X3Zhcl9jMiwgIlxuIiwgIlxuIikpDQogIA0KICBjYXQoIiMjIyMgRGVzY3JpcHRpdmVzIikNCiAgcHN5Y2g6OmRlc2NyaWJlQnkoZGZfbW9kaWYzWywgInZhbHVlIl0sIGxpc3QoZGZfbW9kaWYzWywgIlByZVBvc3QiXSwgZGZfbW9kaWYzWywgIlBvek5lZyJdKSwgbWF0ID0gVFJVRSkgJT4lIA0KICAgIGFzLnRpYmJsZSgpICU+JQ0KICAgIHByaW50KCkNCiAgY2F0KCJcbiIpDQogIA0KICBwcmludChzdGF0X2NvbXApDQogIGNhdCgiXG4iKQ0KICANCiAgY2F0KCIjIyMjIHQgQ2hhbmdlIikNCiAgdGlkeSh0Q2hhbmdlKSAlPiUgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgDQogIGNhdCgiIyMjIyBBTkNPVkEgUG9zdCIpDQogIGNhdCgiXG4iKQ0KICBjYXQoIiMjIyMjIEhvbW9nZW5laXR5IHRlc3QiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkYXNzdW1wJGhvbW8pKQ0KICBjYXQoIiMjIyMjIEFOQ09WQSBvdXRwdXQiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkbWFpbikpDQogICMgdGlkeShtb2RfYW5jb3ZhUG9zdCkgJT4lIA0KICAjICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpICU+JSANCiAgIyAgIHByaW50KCkNCiAgIyBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBQb3N0IEhvYyIpDQogIHByaW50KHRpYmJsZTo6YXMudGliYmxlKGZ1bGxfYW5jb3ZhUG9zdCRwb3N0SG9jW1sxXV0pKQ0KICAjIHRpZHkoc3VtX3Bvc3RIb2NzKSAlPiUgDQogICMgICBtdXRhdGUocC5zaWduaWYgPSBzYXBwbHkocC52YWx1ZSwgZnVuY3Rpb24oeCkgc3RhcnNfc2lnbmlmKHgpKSkgJT4lIA0KICAjICAgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBIb21vZ2VuZWl0eSBvZiByZWdyZXNzaW9uIHNsb3BlcyIpDQogIHN1YmNodW5raWZ5KHBsb3Qoc2NhdHRlciksIDUsIDUpDQp9DQpgYGANCg0KDQojIERlc2NyaXB0aXZlcyAtIEdlbiBWYXJzdGENCg0KYGBge3IgZGVzY19nZW5fdmFyc3RhfQ0KZGVzY3JpYmUoRGF0YV9HZW5fbWVyZ2VkJFZhcnN0YSkNCnByb3AudGFibGUodGFibGUoRGF0YV9HZW5fbWVyZ2VkJEdlbikpDQoNCnQudGVzdChEYXRhX0dlbl9tZXJnZWQkVmFyc3RhIH4gRGF0YV9HZW5fbWVyZ2VkJEdlbikgJT4lDQogIHRpZHkoKQ0KICANCndpbGNveC50ZXN0KERhdGFfR2VuX21lcmdlZCRWYXJzdGEgfiBEYXRhX0dlbl9tZXJnZWQkR2VuKSAlPiUNCiAgdGlkeSgpDQoNCnBzeWNoOjpkZXNjcmliZUJ5KERhdGFfR2VuX21lcmdlZCRWYXJzdGEsIGdyb3VwID0gRGF0YV9HZW5fbWVyZ2VkJEdlbikNCmBgYA0KDQoNCg0KIyBBbmFseXNlcw0KDQojIyBDb3JyZWxhdGlvbnMgYmV0d2VlbiBEaWZmcmVuY2UgU2NvcmVzIHdpdGggb3RoZXIgdmFyaWFibGVzDQoNCmBgYHtyIERfY29yX290aGVyLCByZXN1bHRzPSdhc2lzJ30NCiMjIENvcnJlbGF0aW9ucyBiZXR3ZWVuIERpZmZyZW5jZSBTY29yZXMgd2l0aCBvdGhlciB2YXJpYWJsZXMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9PeF9Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgRF9ER19Qb3osIE5lb19DNCwgTmVvX0UzDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfT3hfTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfQ29ydF9Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgIyBEX1NhbTFfUG96LCBEX1RydXN0VG90X1BveiwgU3RhaVMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9Db3J0X05lZyIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBuaW1pYw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX1Zhc1NfUG96IiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVmFzU19OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgRF9UcnVzdFRvdF9OZWcNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9WYXNCX1BveiIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBEX1NhbTFfUG96DQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVmFzQl9OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgRF9TYW0xX05lZw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX0lPU19Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9JT1NfTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfREdfUG96IiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfREdfTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVHJ1c3RNaW5fUG96IiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVHJ1c3RNaW5fTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVHJ1c3RUb3RfUG96IiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVHJ1c3RUb3RfTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIERfVmFzU19OZWcNCmBgYA0KDQoNCjwhLS0gDQoNCiMjIFNpbXBsZSBiZWZvcmUtYWZ0ZXIgYW5hbHlzZXMgd2l0aCB0IHRlc3QNCg0KYGBge3IgdF90ZXN0LCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCiMjIFNpbXBsZSBiZWZvcmUtYWZ0ZXIgYW5hbHlzZXMgd2l0aCB0IHRlc3QNCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJPeF9wcmVfUG96IiwgIk94X3Bvc3RfUG96IikgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJPeF9wcmVfTmVnIiwgIk94X3Bvc3RfTmVnIikgICMgc2lnDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiQ29ydF9wcmVfUG96IiwgIkNvcnRfcG9zdF9Qb3oiKSAgIyBudSAgDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiQ29ydF9wcmVfTmVnIiwgIkNvcnRfcG9zdF9OZWciKSAgIyBzaWcNCg0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlZhc1NfcHJlUG96IiwgIlZhc1NfcG9zdFBveiIpICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzU19wcmVOZWciLCAiVmFzU19wb3N0TmVnIikgICMgbnUNCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJWYXNCX3ByZVBveiIsICJWYXNCX3Bvc3RQb3oiKSAgIyBzaWcgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlZhc0JfcHJlTmVnIiwgIlZhc0JfcG9zdE5lZyIpICAjIG51DQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiU2FtMV9wcmVQb3oiLCAiU2FtMV9wb3N0UG96IikgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0xX3ByZU5lZyIsICJTYW0xX3Bvc3ROZWciKSAgIyBudQ0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlNhbTJfcHJlUG96IiwgIlNhbTJfcG9zdFBveiIpICAjIG51ICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0yX3ByZU5lZyIsICJTYW0yX3Bvc3ROZWciKSAgIyBudQ0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIklPU19wcmVQb3oiLCAiSU9TX3Bvc3RQb3oiKSAgIyBzaWcgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIklPU19wcmVOZWciLCAiSU9TX3Bvc3ROZWciKSAgIyBudQ0KDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiREdfcHJlUG96VG90IiwgIkRHX3Bvc3RQb3pUb3QiKSAgIyBudSAgDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiREdfcHJlTmVnVG90IiwgIkRHX3Bvc3ROZWdUb3QiKSAgIyBzaWcNCg0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0TWluUG96UHJlIiwgIlRydXN0TWluUG96UG9zdCIpICAjIG51ICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJUcnVzdE1pbk5lZ1ByZSIsICJUcnVzdE1pbk5lZ1Bvc3QiKSAgIyBudQ0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0VG90UG96UHJlIiwgIlRydXN0VG90UG96UG9zdCIpICAjIG51ICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJUcnVzdFRvdE5lZ1ByZSIsICJUcnVzdFRvdE5lZ1Bvc3QiKSAgIyBudQ0KYGBgDQoNCg0KIyMgdENoYW5jZSBhbmQgQU5DT1ZBUG9zdA0KDQpgYGB7ciB0X0NoYW5nZV9BTkNPVkFfUG9zdHMsIGZpZy53aWR0aD0xMSwgZmlnLmhlaWdodD0xMiwgcmVzdWx0cz0nYXNpcyd9DQojIyB0Q2hhbmNlIGFuZCBBTkNPVkFQb3N0IA0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJPeF9wcmVfUG96IiwgIk94X3Bvc3RfUG96IiwgIk94X3ByZV9OZWciLCAiT3hfcG9zdF9OZWciKQ0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJDb3J0X3ByZV9Qb3oiLCAiQ29ydF9wb3N0X1BveiIsICJDb3J0X3ByZV9OZWciLCAiQ29ydF9wb3N0X05lZyIpDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzU19wcmVQb3oiLCAiVmFzU19wb3N0UG96IiwgIlZhc1NfcHJlTmVnIiwgIlZhc1NfcG9zdE5lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIlZhc0JfcHJlUG96IiwgIlZhc0JfcG9zdFBveiIsICJWYXNCX3ByZU5lZyIsICJWYXNCX3Bvc3ROZWciKQ0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0xX3ByZVBveiIsICJTYW0xX3Bvc3RQb3oiLCAiU2FtMV9wcmVOZWciLCAiU2FtMV9wb3N0TmVnIikNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiU2FtMl9wcmVQb3oiLCAiU2FtMl9wb3N0UG96IiwgIlNhbTJfcHJlTmVnIiwgIlNhbTJfcG9zdE5lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIklPU19wcmVQb3oiLCAiSU9TX3Bvc3RQb3oiLCAiSU9TX3ByZU5lZyIsICJJT1NfcG9zdE5lZyIpIA0KDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIkRHX3ByZVBvelRvdCIsICJER19wb3N0UG96VG90IiwgIkRHX3ByZU5lZ1RvdCIsICJER19wb3N0TmVnVG90IikgDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVHJ1c3RNaW5Qb3pQcmUiLCAiVHJ1c3RNaW5Qb3pQb3N0IiwgIlRydXN0TWluTmVnUHJlIiwgIlRydXN0TWluTmVnUG9zdCIpIA0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJUcnVzdFRvdFBvelByZSIsICJUcnVzdFRvdFBvelBvc3QiLCAiVHJ1c3RUb3ROZWdQcmUiLCAiVHJ1c3RUb3ROZWdQb3N0IikgDQpgYGANCg0KDQotLT4gDQoNCg0KIyMgU2ltcGxlIGJlZm9yZS1hZnRlciBhbmFseXNlcyB3aXRoIHQgdGVzdCBieSBHZW5kZXINCg0KYGBge3IgdF90ZXN0X2dlbiwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojIEZlbWFsZXMNCmNhdCgiIyMjIEZlbWFsZXMiKQ0KIyBmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiT3hfcHJlX1BveiIsICJPeF9wb3N0X1BveiIsIHRlc3RfbWV0aG9kID0gIndpbGNveC50ZXN0IikgICAgICMgbnMgDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiT3hfcHJlX1BveiIsICJPeF9wb3N0X1BveiIpICAjIG5zDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiT3hfcHJlX05lZyIsICJPeF9wb3N0X05lZyIpICAgICAjIHNpZw0KIyBmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiQ29ydF9wcmVfUG96IiwgIkNvcnRfcG9zdF9Qb3oiKSAgIyBucyAgDQojIGZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJDb3J0X3ByZV9OZWciLCAiQ29ydF9wb3N0X05lZyIpICAjIHNpZw0KDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiVmFzU19wcmVQb3oiLCAiVmFzU19wb3N0UG96IikgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJWYXNTX3ByZU5lZyIsICJWYXNTX3Bvc3ROZWciKSAgIyBucw0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIlZhc0JfcHJlUG96IiwgIlZhc0JfcG9zdFBveiIpICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiVmFzQl9wcmVOZWciLCAiVmFzQl9wb3N0TmVnIikgICMgbnMNCiMgZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIlNhbTFfcHJlUG96IiwgIlNhbTFfcG9zdFBveiIpICAjIHNpZyAgDQojIGZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJTYW0xX3ByZU5lZyIsICJTYW0xX3Bvc3ROZWciKSAgIyBudQ0KIyBmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiU2FtMl9wcmVQb3oiLCAiU2FtMl9wb3N0UG96IikgICMgbnUgIA0KIyBmdW5jX3RfYm94KERhdGFfZmVtLCAiSUQiLCAiU2FtMl9wcmVOZWciLCAiU2FtMl9wb3N0TmVnIikgICMgbnUNCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJJT1NfcHJlUG96IiwgIklPU19wb3N0UG96IikgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJJT1NfcHJlTmVnIiwgIklPU19wb3N0TmVnIikgICMgbnMNCg0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIkRHX3ByZVBvelRvdCIsICJER19wb3N0UG96VG90IikgICMgbnMgIA0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIkRHX3ByZU5lZ1RvdCIsICJER19wb3N0TmVnVG90IikgICMgbnMNCg0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIlRydXN0TWluUG96UHJlIiwgIlRydXN0TWluUG96UG9zdCIpICAjIG5zICANCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJUcnVzdE1pbk5lZ1ByZSIsICJUcnVzdE1pbk5lZ1Bvc3QiKSAgIyBucw0KZnVuY190X2JveChEYXRhX2ZlbSwgIklEIiwgIlRydXN0VG90UG96UHJlIiwgIlRydXN0VG90UG96UG9zdCIpICAjIG5zICANCmZ1bmNfdF9ib3goRGF0YV9mZW0sICJJRCIsICJUcnVzdFRvdE5lZ1ByZSIsICJUcnVzdFRvdE5lZ1Bvc3QiKSAgIyBucw0KYGBgDQoNCg0KPCEtLSANCg0KIyMgdENoYW5jZSBhbmQgQU5DT1ZBUG9zdCBieSBHZW5kZXINCg0KYGBge3IgdF9DaGFuZ2VfQU5DT1ZBX1Bvc3RzX2dlbiwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTEyLCByZXN1bHRzPSdhc2lzJ30NCiMjIHRDaGFuY2UgYW5kIEFOQ09WQVBvc3QgDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIk94X3ByZV9Qb3oiLCAiT3hfcG9zdF9Qb3oiLCAiT3hfcHJlX05lZyIsICJPeF9wb3N0X05lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIkNvcnRfcHJlX1BveiIsICJDb3J0X3Bvc3RfUG96IiwgIkNvcnRfcHJlX05lZyIsICJDb3J0X3Bvc3RfTmVnIikNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJWYXNTX3ByZVBveiIsICJWYXNTX3Bvc3RQb3oiLCAiVmFzU19wcmVOZWciLCAiVmFzU19wb3N0TmVnIikNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzQl9wcmVQb3oiLCAiVmFzQl9wb3N0UG96IiwgIlZhc0JfcHJlTmVnIiwgIlZhc0JfcG9zdE5lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIlNhbTFfcHJlUG96IiwgIlNhbTFfcG9zdFBveiIsICJTYW0xX3ByZU5lZyIsICJTYW0xX3Bvc3ROZWciKQ0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0yX3ByZVBveiIsICJTYW0yX3Bvc3RQb3oiLCAiU2FtMl9wcmVOZWciLCAiU2FtMl9wb3N0TmVnIikNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiSU9TX3ByZVBveiIsICJJT1NfcG9zdFBveiIsICJJT1NfcHJlTmVnIiwgIklPU19wb3N0TmVnIikgDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiREdfcHJlUG96VG90IiwgIkRHX3Bvc3RQb3pUb3QiLCAiREdfcHJlTmVnVG90IiwgIkRHX3Bvc3ROZWdUb3QiKSANCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJUcnVzdE1pblBvelByZSIsICJUcnVzdE1pblBvelBvc3QiLCAiVHJ1c3RNaW5OZWdQcmUiLCAiVHJ1c3RNaW5OZWdQb3N0IikgDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0VG90UG96UHJlIiwgIlRydXN0VG90UG96UG9zdCIsICJUcnVzdFRvdE5lZ1ByZSIsICJUcnVzdFRvdE5lZ1Bvc3QiKSANCmBgYA0KDQoNCi0tPg0KDQoNCg0KPCEtLQ0KDQojIyBDb3JyZWxhdGlvbnMgd2l0aCBPeHkNCg0KYGBge3IgY29yX094LCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCiMjIE1pbmluZyBDb3JyZWxhdGlvbnMgd2l0aCBPeHkNCmRmX094eUFsbF9jb3IgPC0NCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgJT4lDQogICAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJPeCIsIC4pKSkgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG9ubHkgT3h5LCBidXQgYm90aCBQcmUgYW5kIFBvc3QgT3h5DQoNCmRmX094eUFsbF9jb3IgJT4lICAgICAgICAgICAgICANCiAgICBwcmludChuID0gSW5mKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCmRmX094eUFsbF9jb3IgJT4lDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KIA0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQcmUgbWVhc3VyZXMgd2l0aCBPeHkgLS0gbm90aGluZw0KZGZfT3h5UHJlX2NvciA8LSANCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4xKSAlPiUNCiAgICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogICAgZmlsdGVyX2F0KHZhcnMoZmVhdHVyZV8xLCBmZWF0dXJlXzIpLCBhbGxfdmFycyhncmVwbCgicHJlfFByZSIsIC4pKSkgJT4lDQogICAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIk94IiwgLikpKSANCg0KZGZfT3h5UHJlX2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQb3N0IG1lYXN1cmVzIHdpdGggT3h5DQpkZl9PeHlQb3N0X2NvciA8LQ0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICAgIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwb3N0fFBvc3QiLCAuKSkpICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJPeCIsIC4pKSkgDQoNCmRmX094eVBvc3RfY29yICU+JQ0KICAgIHByaW50KG4gPSBJbmYpDQpkZl9PeHlQb3N0X2NvciAlPiUgDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KYGBgDQoNCg0KIyMgQ29ycmVsYXRpb25zIHdpdGggU3Rlc3MNCg0KYGBge3IgY29yX1Zhc1MsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgTWluaW5nIENvcnJlbGF0aW9ucyB3aXRoIFZhc1MNCmRmX1Zhc1NBbGxfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICU+JQ0KICAgIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiVmFzUyIsIC4pKSkgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG9ubHkgVmFzUywgYnV0IGJvdGggUHJlIGFuZCBQb3N0IFZhc1MNCg0KZGZfVmFzU0FsbF9jb3IgJT4lICAgICAgICAgICAgICANCiAgICBwcmludChuID0gSW5mKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQcmUgbWVhc3VyZXMgd2l0aCBWYXNTDQpkZl9WYXNTUHJlX2NvciA8LSANCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4xKSAlPiUNCiAgICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogICAgZmlsdGVyX2F0KHZhcnMoZmVhdHVyZV8xLCBmZWF0dXJlXzIpLCBhbGxfdmFycyhncmVwbCgicHJlfFByZSIsIC4pKSkgJT4lDQogICAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIlZhc1MiLCAuKSkpIA0KDQpkZl9WYXNTUHJlX2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCmRmX1Zhc1NQcmVfY29yICU+JSANCiAgZnVuY19kb3RwbG90X2NvcigpDQoNCiMgQ29ycmVsYXRpb25zIG9ubHkgb24gUG9zdCBtZWFzdXJlcyB3aXRoIFZhc1MNCmRmX1Zhc1NQb3N0X2NvciA8LQ0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICAgIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwb3N0fFBvc3QiLCAuKSkpICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJWYXNTIiwgLikpKSANCg0KZGZfVmFzU1Bvc3RfY29yICU+JQ0KICAgIHByaW50KG4gPSBJbmYpDQpkZl9WYXNTUG9zdF9jb3IgJT4lIA0KICBmdW5jX2RvdHBsb3RfY29yKCkNCmBgYA0KDQoNCiMjIENvcnJlbGF0aW9ucyB3aXRoIFdlbGwgQmVpbmcNCg0KYGBge3IgY29yX1Zhc0IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgTWluaW5nIENvcnJlbGF0aW9ucyB3aXRoIFZhc0INCmRmX1Zhc0JBbGxfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICU+JQ0KICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJWYXNCIiwgLikpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICMgb25seSBWYXNCLCBidXQgYm90aCBQcmUgYW5kIFBvc3QgVmFzQg0KDQpkZl9WYXNCQWxsX2NvciAlPiUgICAgICAgICAgICAgIA0KICBwcmludChuID0gSW5mKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQcmUgbWVhc3VyZXMgd2l0aCBWYXNCDQpkZl9WYXNCUHJlX2NvciA8LSANCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4xKSAlPiUNCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwcmV8UHJlIiwgLikpKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIlZhc0IiLCAuKSkpIA0KDQpkZl9WYXNCUHJlX2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCmRmX1Zhc0JQcmVfY29yICU+JQ0KICBmdW5jX2RvdHBsb3RfY29yKCkNCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQb3N0IG1lYXN1cmVzIHdpdGggVmFzQg0KZGZfVmFzQlBvc3RfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMSkgJT4lDQogIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgZmlsdGVyX2F0KHZhcnMoZmVhdHVyZV8xLCBmZWF0dXJlXzIpLCBhbGxfdmFycyhncmVwbCgicG9zdHxQb3N0IiwgLikpKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIlZhc0IiLCAuKSkpIA0KDQpkZl9WYXNCUG9zdF9jb3IgJT4lDQogIHByaW50KG4gPSBJbmYpDQpkZl9WYXNCUG9zdF9jb3IgJT4lIA0KICBmdW5jX2RvdHBsb3RfY29yKCkNCmBgYA0KDQoNCiMjIENvcnJlbGF0aW9ucyB3aXRoIElPUyANCg0KYGBge3IgY29yX0lPUywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojIyBNaW5pbmcgQ29ycmVsYXRpb25zIHdpdGggSU9TDQpkZl9JT1NBbGxfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICU+JQ0KICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJJT1MiLCAuKSkpICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBvbmx5IElPUywgYnV0IGJvdGggUHJlIGFuZCBQb3N0IElPUw0KDQpkZl9JT1NBbGxfY29yICU+JSAgICAgICAgICAgICAgDQogIHByaW50KG4gPSBJbmYpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFByZSBtZWFzdXJlcyB3aXRoIElPUw0KZGZfSU9TUHJlX2NvciA8LSANCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4xKSAlPiUNCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwcmV8UHJlIiwgLikpKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIklPUyIsIC4pKSkgDQoNCmRmX0lPU1ByZV9jb3IgJT4lDQogIHByaW50KG4gPSBJbmYpDQpkZl9JT1NQcmVfY29yICU+JQ0KICBmdW5jX2RvdHBsb3RfY29yKCkNCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQb3N0IG1lYXN1cmVzIHdpdGggSU9TDQpkZl9JT1NQb3N0X2NvciA8LQ0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogIGZpbHRlcl9hdCh2YXJzKGZlYXR1cmVfMSwgZmVhdHVyZV8yKSwgYWxsX3ZhcnMoZ3JlcGwoInBvc3R8UG9zdCIsIC4pKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJJT1MiLCAuKSkpIA0KDQpkZl9JT1NQb3N0X2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCmRmX0lPU1Bvc3RfY29yICU+JSANCiAgZnVuY19kb3RwbG90X2NvcigpDQpgYGANCg0KDQoNCi0tPg0KDQoNCjxicj4NCg0KDQoNCjwhLS0gU2Vzc2lvbiBJbmZvIGFuZCBMaWNlbnNlIC0tPg0KDQo8YnI+DQoNCiMgU2Vzc2lvbiBJbmZvDQpgYGB7ciBzZXNzaW9uX2luZm8sIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9ICdtYXJrdXAnfQ0Kc2Vzc2lvbkluZm8oKSAgICANCmBgYA0KDQo8IS0tIEZvb3RlciAtLT4NCiZuYnNwOw0KPGhyIC8+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+QSB3b3JrIGJ5IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9DbGF1ZGl1UGFwYXN0ZXJpLyI+Q2xhdWRpdSBQYXBhc3Rlcmk8L2E+PC9wPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjogIzgwODA4MDsiPjxlbT5jbGF1ZGl1LnBhcGFzdGVyaUBnbWFpbC5jb208L2VtPjwvc3Bhbj48L3A+DQombmJzcDsNCg==